package app

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"web-service-gin/src/app/config"
	"web-service-gin/src/app/router"
	"web-service-gin/src/pkg/httpx"
	"web-service-gin/src/pkg/logx"

	"web-service-gin/src/pkg/storage"

	"github.com/toolkits/pkg/errorx"
)

type App struct {
	Config string
}

type Option func(app *App)

func SetConfig(conf string) Option {
	return func(app *App) {
		app.Config = conf
	}
}
func Run(opts ...Option) {
	var (
		app = &App{}
		ch  = make(chan os.Signal, 1)
	)

	signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

	for _, opt := range opts {
		opt(app)
	}
	clean, err := app.initialize()
	if err != nil {
		errorx.Bomb(1, "init fail err is : %s", err.Error())
	}
Exit:
	for {
		sign := <-ch
		switch sign {
		case syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
			break Exit
		case syscall.SIGHUP:
			fmt.Printf("SIGHUP\n")
		default:
			break Exit
		}
	}
	clean()
	fmt.Println("safe exit")
}

func (a App) initialize() (func(), error) {
	config.MustLoad(a.Config)

	storage.InitDB(config.C.DB)

	redisClean := storage.InitRedis(config.C.Redis)

	logClean := logx.InitLog(config.C.Log)

	engine := router.New()

	httpClean := httpx.InitHttp(config.C.Http, engine)

	return func() {
		redisClean()
		httpClean()
		logClean()
	}, nil
}
